/* Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.yzbdl.lanius.orchestrate.system.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.yzbdl.lanius.orchestrate.serv.dto.system.*;
import org.yzbdl.lanius.orchestrate.serv.entity.system.OrgEntity;
import org.yzbdl.lanius.orchestrate.serv.service.system.ManagerAuthService;
import org.yzbdl.lanius.orchestrate.serv.service.system.ManagerService;
import org.yzbdl.lanius.orchestrate.serv.service.system.OrgService;
import org.yzbdl.lanius.orchestrate.serv.service.system.UserService;
import org.yzbdl.lanius.orchestrate.serv.utils.CurrentUserUtil;
import org.yzbdl.lanius.orchestrate.serv.utils.VerifyCodeUtil;
import org.yzbdl.lanius.orchestrate.common.chain.DeleteCheckChain;
import org.yzbdl.lanius.orchestrate.common.chain.DeleteExploreDto;
import org.yzbdl.lanius.orchestrate.common.exception.runtime.BusinessException;
import org.yzbdl.lanius.orchestrate.common.exception.runtime.InvalidCodeException;
import org.yzbdl.lanius.orchestrate.common.result.ResultObj;
import org.yzbdl.lanius.orchestrate.common.utils.MessageUtil;
import org.yzbdl.lanius.orchestrate.common.utils.SpringUtil;

import java.util.ArrayList;

/**
 * 管理员访问接口
 *
 * @author chenjunhao
 * @date 2022-04-08 12:48
 */
@Api(tags = "管理员接口")
@RestController
@RequestMapping("/manager")
@Validated
public class ManagerController {

    @Autowired
    ManagerService managerService;

    @Autowired
    ManagerAuthService managerAuthService;

    @Autowired
    OrgService orgService;

    @Autowired
    UserService userService;

    DataSourceTransactionManager dataSourceTransactionManager = SpringUtil.getBean(DataSourceTransactionManager.class);
    TransactionDefinition transactionDefinition = SpringUtil.getBean(TransactionDefinition.class);


    @ApiOperation(value="管理员登录", notes="")
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public ResultObj login(@RequestBody ManagerLoginParamDto managerLoginParamDto,@RequestParam String key){
        if(VerifyCodeUtil.verify(key,managerLoginParamDto.getCode())){
            return ResultObj.success(managerAuthService.login(managerLoginParamDto.getUserName(), managerLoginParamDto.getPassword()));
        }
        throw new InvalidCodeException("验证码验证失败！");
    }

    @ApiOperation(value="刷新token", notes="")
    @RequestMapping(value = "/refresh", method = RequestMethod.POST)
    public ResultObj refresh(@RequestBody @Validated TokenRefreshDto tokenRefreshDto){
        return ResultObj.success(managerAuthService.refresh(tokenRefreshDto.getRefreshToken()));
    }

    @ApiOperation(value="管理员添加", notes="")
    @RequestMapping(value = "", method = RequestMethod.POST)
    public ResultObj insert(@RequestBody @Validated ManagerInsertParamDto managerInsertParamDto){
        return ResultObj.success(managerService.insertManager(managerInsertParamDto));
    }

    @ApiOperation(value="分页查看管理员", notes="")
    @RequestMapping(value = "/query", method = RequestMethod.POST)
    public ResultObj listManagerPage(@RequestParam(defaultValue = "20") int size, @RequestParam(defaultValue = "1") int page,@RequestBody @Validated ManagerListDto managerListDto){
        return ResultObj.success(managerService.listManagerPage(managerListDto,new Page<>(page,size)));
    }

    @ApiOperation(value="删除管理员", notes="")
    @RequestMapping(value = "{managerId}", method = RequestMethod.DELETE)
    public ResultObj deleteManagerById(@PathVariable("managerId") String managerId){
        if(managerService.count()<=1){
            return ResultObj.error("不能删除唯一的管理员");
        }
        return ResultObj.success(managerService.removeById(managerId));
    }

    @ApiOperation(value="新增组织并关联用户")
    @RequestMapping(value = "/org", method = RequestMethod.POST)
    public ResultObj insertOrg(@RequestBody @Validated OrgParamDto orgParamDto){
        if(orgService.existOrg(orgParamDto.getOrgName())){
            return ResultObj.error(MessageUtil.get("system.org.same_org_name"));
        }
        if(userService.isExistUserById(orgParamDto.getUserId())){
            return ResultObj.success(orgService.insertOrgRelateUser(orgParamDto));
        }
        return ResultObj.error("未找到该用户！");
    }

    @ApiOperation(value="新增组织并新增用户")
    @RequestMapping(value = "/emptyOrg", method = RequestMethod.POST)
    public ResultObj insertOrgAndUser(@RequestBody @Validated OrgUserParamDto orgUserParamDto){
        if(orgService.existOrg(orgUserParamDto.getOrgName())){
            return ResultObj.error(MessageUtil.get("system.org.same_org_name"));
        }
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try{
            OrgEntity orgEntity = OrgEntity.builder().orgName(orgUserParamDto.getOrgName()).frozen(false).build();
            orgService.save(orgEntity);
            UserInsertParamDto userInsertParamDto = UserInsertParamDto.builder()
                    .userName(orgUserParamDto.getUserName())
                    .nickName(orgUserParamDto.getNickName())
                    .password(orgUserParamDto.getPassword())
                    .build();
            userService.insertUser(userInsertParamDto,orgEntity.getId(),true);
            dataSourceTransactionManager.commit(transactionStatus);
            return ResultObj.success("成功！");
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            if(e.getClass().equals(BusinessException.class)){
                return ResultObj.error(((BusinessException)e).getErrMsg());
            }
            return ResultObj.error(e.getMessage());
        }
    }

    @ApiOperation(value="分页查看组织", notes="")
    @RequestMapping(value = "/org/query", method = RequestMethod.POST)
    public ResultObj queryOrg(@RequestParam int size, @RequestParam int page,@RequestBody OrgQueryDto orgQueryDto){
        return ResultObj.success(orgService.listOrgPage(orgQueryDto,new Page<>(page, size)));
    }

    @ApiOperation(value="查看所有组织", notes="")
    @RequestMapping(value = "/org", method = RequestMethod.GET)
    public ResultObj queryAllOrg(@RequestParam(required = false) String orgName){
        return ResultObj.success(orgService.listOrgByOrgName(orgName));
    }

    @ApiOperation(value="查看组织用户", notes="")
    @RequestMapping(value = "/user/query", method = RequestMethod.POST)
    public ResultObj queryUser(@RequestParam int pageSize, @RequestParam int pageNum,@RequestBody ManagerUserQueryDto managerUserQueryDto){
        return ResultObj.success(userService.listUserPage(managerUserQueryDto,new Page<>(pageNum, pageSize)));
    }

    @ApiOperation(value="修改组织", notes="")
    @RequestMapping(value = "/org", method = RequestMethod.PUT)
    public ResultObj updateOrg(@RequestBody @Validated OrgParamIdDto orgParamIdDto){
        OrgEntity orgEntity = OrgEntity.builder().orgName(orgParamIdDto.getOrgName()).build();
        orgEntity.setId(orgParamIdDto.getId());
        return ResultObj.success(orgService.updateOrg(orgEntity));
    }

//    @ApiOperation(value="新增组织用户", notes="")
//    @RequestMapping(value = "/org/user", method = RequestMethod.POST)
//    public ResultObj insertOrgUser(@RequestBody OrgUserDto orgUserDto){
//        return ResultObj.success(userService.insertUser(orgUserDto.userInsertParamDtoInstance(),orgUserDto.getOrgId(),true));
//    }

    @ApiOperation(value="删除组织", notes="")
    @RequestMapping(value = "/org/{id}", method = RequestMethod.DELETE)
    public ResultObj deleteOrgById(@PathVariable("id") Long id){
        DeleteExploreDto deleteExploreDto = new DeleteCheckChain()
                .addChain(!userService.isExistUserByOrgId(id), () -> orgService.removeById(id), "该组织存在用户！不能删除")
                .process();
        return deleteExploreDto.isOk()?
                ResultObj.success("成功！"):ResultObj.error(deleteExploreDto.getReason());
    }

    @ApiOperation(value="冻结组织", notes="")
    @RequestMapping(value = "/org/{orgId}/frozen", method = RequestMethod.POST)
    public ResultObj deleteOrgById(@RequestBody @Validated ManagerOrgFrozenDto managerOrgFrozenDto,@PathVariable("orgId") Long orgId){
        return ResultObj.success(orgService.changeOrgFrozen(managerOrgFrozenDto.getFrozen(),orgId));
    }

    @ApiOperation(value="根据用户名查询用户", notes="")
    @RequestMapping(value = "/org/user", method = RequestMethod.GET)
    public ResultObj listUserByUserName(@RequestParam String userName){
        if(StringUtils.isNotBlank(userName)){
            return ResultObj.success(userService.listUserByUserName(userName));
        }
        return ResultObj.success(new ArrayList<>());
    }

    @ApiOperation(value="修改密码", notes="")
    @RequestMapping(value = "/password", method = RequestMethod.POST)
    public ResultObj updatePassword(@RequestBody @Validated UpdatePasswordDto updatePasswordDto){
        return ResultObj.success(managerAuthService.updatePassword(
                CurrentUserUtil.getCurrentUserId(),
                updatePasswordDto.getNewPassword(),
                updatePasswordDto.getOldPassword()
        ));
    }

}
